///////////////////////////////////////////////////////////////////////////// 
/* 
  Copyright 2004 Ronald S. Burkey <info@sandroid.org>
 
  This file is part of GutenMark. 
 
  GutenMark is free software; you can redistribute it and/or modify 
  it under the terms of the GNU General Public License as published by 
  the Free Software Foundation; either version 2 of the License, or 
  (at your option) any later version. 
 
  GutenMark is distributed in the hope that it will be useful, 
  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  GNU General Public License for more details. 
 
  You should have received a copy of the GNU General Public License 
  along with GutenMark; if not, write to the Free Software 
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
  Filename:	GutenSplit.c 
  Purpose:	Splits the HTML files output by GutenMark into smaller
  		HTML files at <h1> boundaries, and adds a table of 
		contents and links between the files. 
  Mods:		01/21/04 RSB	Wrote. 
  		02/21/04 RSB	Oops!  Forgot to add the HTML header to
				the files after the first two.

  I don't know if this program works on arbitrary HTML files, as it
  is specialized to GutenMark output files.  It might, for all I know.
*/

#include <stdio.h>
#include <string.h>

// A buffer used for holding the header of the document --- i.e., the stuff up
// to and including <body>.  It is assumed that this is followed by a bunch 
// of stuff, followed by </body></html>.
static char HeaderBuffer[32768];
static int HeaderSize = 0;

// A buffer used for inputting lines from the file.
static char LineBuffer[16384];
//static int LineSize;

// A buffer for the filename.
static char Filename[1024];

// A buffer for the title.
static char Title[1024];

int
main (int argc, char *argv[])
{
  int i, j, RetVal = 1, Index = 0, Headings = 0, InH1 = 0;
  char *s = NULL, *ss, *InputFile = NULL, *OutputBase = NULL;
  FILE *fin = NULL, *fout = NULL, *toc = NULL;
  
  printf ("GutenSplit --- An HTML-splitter provided with GutenMark.\n");
  printf ("Version " __DATE__ "\n");
  printf ("Copyright (C)2004 Ronald Burkey\n");

  // First, parse the command-line inputs.
  RetVal = 1;
  for (i = 1; i < argc; i++)
    {
      if (!strcmp (argv[i], "--help") || !strcmp (argv[i], "/?"))
        {
	Usage:
	  printf ("USAGE:\n");
	  printf ("\tGutenSplit [OPTIONS] InputFile OutputBase\n");
	  printf ("The InputFile is the name of an HTML file as output by\n");
	  printf ("GutenMark.  The OutputBase is a basename of HTML files\n");
	  printf ("which will be created by GutenSplit.  For example, if\n");
	  printf ("OutputBase is \"TomSawyer\", then GutenSplit will create\n");
	  printf ("HTML files called TomSawyer000.html, TomSawyer001.html,\n");
	  printf ("and so on.  The first of these will be the table of contents.\n");
	  printf ("There are presently no OPTIONS, other than --help.\n");
	  goto Done;
	}
      else if ('-' == argv[i][0])
        {
	  printf ("Unrecognized command-line switch.\n");
	  goto Usage;
	}
      else if (InputFile == NULL)
        InputFile = argv[i];
      else if (OutputBase == NULL)
        OutputBase = argv[i];
      else
        {
	  printf ("Too many command-line arguments.\n");
	  goto Usage;
	}
    }
  if (OutputBase == NULL)
    {
      printf ("Too few command-line arguments.\n");
      goto Usage;
    }
  fin = fopen (InputFile, "r");
  if (fin == NULL)
    {
      printf ("The chosen input file (\"%s\") was not found.\n", InputFile);
      goto Usage;
    }
  sprintf (Filename, "%s%03d.html", OutputBase, Index++);
  toc = fopen (Filename, "w");
  if (toc == NULL)
    {
      printf ("Cannot create the table-of-contents output file.\n");
      goto Usage;
    }
  sprintf (Filename, "%s%03d.html", OutputBase, Index++);
  fout = fopen (Filename, "w");
  if (fout == NULL)
    {
      printf ("Cannot create output file 001.\n");
      goto Usage;
    }

  // Read the header of the input file.  We don't do any checking of the HTML
  // at all.  We assume it's valid HTML, and we assume that the <body>...</body>
  // area is completely carved up with <h1> headings.
  RetVal = 2;
  LineBuffer[sizeof (LineBuffer) - 1] = 0;
  for (HeaderSize = 0; NULL != fgets (LineBuffer, sizeof (LineBuffer) - 1, fin); )
    {
      s = strstr (LineBuffer, "<title>");
      ss = strstr (LineBuffer, "</title>");
      if (s != NULL && ss != NULL)
        {
	  *ss = 0;
	  strcpy (Title, s + 7);
	  *ss = '<';
	}
      s = strstr (LineBuffer, "<body>");
      if (s == NULL)
        j = strlen (LineBuffer);
      else 
        {
	  s += 6;
          j = s - LineBuffer;
	}
      if (HeaderSize + j > sizeof (HeaderBuffer))
        {
	  printf ("The size of this file\'s header has exceeded the max allowed.\n");
	  printf ("Perhaps this is not an HTML file.\n");
	  goto Usage;
	}
      for (i = 0; i < j; i++)
        HeaderBuffer[HeaderSize++] = LineBuffer[i];
      if (s != NULL)
        break;
    }

  // Write header to the table of contents and first section.
  RetVal = 3;
  if (HeaderSize != fwrite (HeaderBuffer, 1, HeaderSize, toc))
    {
      printf ("Write-error in table of contents header.\n");
      goto Usage;
    }
  fprintf (toc, "<h1 style=\"text-align: center;\">%s</h1>\n", Title);
  fprintf (toc, "<hr style=\"width: 100%%; height: 2px;\">");
  fprintf (toc, "<h1>Table of Contents</h1>\n");
  fprintf (toc, "<ul>\n");
  if (HeaderSize != fwrite (HeaderBuffer, 1, HeaderSize, fout))
    {
      printf ("Write-error in output file 001.\n");
      goto Usage;
    }
  fprintf (fout, "<h1 style=\"text-align: center;\">%s</h1>\n", Title);
  fprintf (fout, "<div style=\"text-align: center;\">");
  fprintf (fout, "<a href=\"%s000.html\">Contents</a> &nbsp;&nbsp;", OutputBase);
  fprintf (fout, "<a href=\"%s%03d.html\">Next</a></div>\n", OutputBase, Index);
  fprintf (fout, "<hr style=\"width: 100%%; height: 2px;\">");

  // Now begin parsing the input for the non-header stuff.  Some of it
  // may still be lingering in s.
  RetVal = 4;
  for (;;)
    {
      // Get new input, if none already lingering.
      if (s == NULL)
        {
	  s = fgets (LineBuffer, sizeof (LineBuffer) - 1, fin);
	  if (s == NULL)
	    break;
	}
      // If still in the midst of a heading, take care of it.
    StillInH1:
      if (InH1)
        {
	  ss = strstr (s, "</h1>");
	  if (ss == NULL)
	    {
	      fprintf (toc, "%s", s);
	      fprintf (fout, "%s", s);
	      s = NULL;
	      continue;
	    }
	  else
	    {
	      *ss = 0;
	      fprintf (fout, "%s</h1>\n", s);
	      fprintf (toc, "%s</a></li>\n", s);
	      InH1 = 0;
	      s = ss + 5;
	    }
	}
      // Check for start of new heading.
      ss = strstr (s, "<h1>");
      if (ss != NULL)
        {
          *ss = 0;
	  fprintf (fout, "%s", s);
	  s = ss + 4;
	  // Go to next output file.  For the FIRST heading we encounter,
	  // we're actually already there and don't need to worry about it.
	  Headings++;
	  if (Headings != 1)
	    {
              fprintf (fout, "<hr style=\"width: 100%%; height: 2px;\">\n");
              fprintf (fout, "<div style=\"text-align: center;\">");
              fprintf (fout, "<a href=\"%s%03d.html\">Previous</a> &nbsp;&nbsp;", OutputBase, Index - 2);
              fprintf (fout, "<a href=\"%s000.html\">Contents</a> &nbsp;&nbsp;", OutputBase);
              fprintf (fout, "<a href=\"%s%03d.html\">Next</a></div>\n", OutputBase, Index);
              fprintf (fout, "\n</body>\n</html>\n");	      fclose (fout);
              sprintf (Filename, "%s%03d.html", OutputBase, Index++);
              fout = fopen (Filename, "w");
              if (fout == NULL)
                {
                  printf ("Cannot create output file %03d.\n", Index - 1);
                  goto Usage;
                }
	      fprintf (fout, "%s\n", HeaderBuffer);
              fprintf (fout, "<h1 style=\"text-align: center;\">%s</h1>\n", Title);
              fprintf (fout, "<div style=\"text-align: center;\">");
              fprintf (fout, "<a href=\"%s%03d.html\">Previous</a> &nbsp;&nbsp;", OutputBase, Index - 2);
              fprintf (fout, "<a href=\"%s000.html\">Contents</a> &nbsp;&nbsp;", OutputBase);
              fprintf (fout, "<a href=\"%s%03d.html\">Next</a></div>\n", OutputBase, Index);
              fprintf (fout, "<hr style=\"width: 100%%; height: 2px;\">\n");
	    }
          fprintf (fout, "<h1>");
	  fprintf (toc, "<li><a href=\"%s%03d.html\">", OutputBase, Index - 1);
	  InH1 = 1;
	  goto StillInH1;
	}
      // If we've gotten to here, we're not in a heading, and the string
      // doesn't contain any new heading starts.  Check for end-of-body.
      ss = strstr (s, "</body>");
      if (ss != NULL)
        {
	  *ss = 0;
	  fprintf (fout, "%s", s);
	  break;	// All done!
	}
      // Okay, contains nothing fishy at all.
      fprintf (fout, "%s", s);
      s = NULL;
    }

  // All done!
  RetVal = 0;
Done:
  if (fin != NULL)
    fclose (fin);
  if (toc != NULL)
    {
      fprintf (toc, "</ul>\n");
      fprintf (toc, "<hr style=\"width: 100%%; height: 2px;\">\n");
      fprintf (toc, "<div style=\"text-align: center;\">");
      fprintf (toc, "<a href=\"%s001.html\">Begin</a></div>\n", OutputBase);
      fprintf (toc, "</body>\n</html>\n");
      fclose (toc);
    }
  if (fout != NULL)
    {
      fprintf (fout, "<hr style=\"width: 100%%; height: 2px;\">");
      fprintf (fout, "<div style=\"text-align: center;\">");
      fprintf (fout, "<a href=\"%s%03d.html\">Previous</a> &nbsp;&nbsp;", OutputBase, Index - 2);
      fprintf (fout, "<a href=\"%s000.html\">Contents</a> &nbsp;&nbsp;", OutputBase);
      fprintf (fout, "<a href=\"%s%03d.html\">Next</a></div>\n", OutputBase, Index);
      fprintf (fout, "\n</body>\n</html>\n");
      fclose (fout);
      // Add a fictitious last page, so that the "Next" links above will have
      // something to refer to.
      sprintf (Filename, "%s%03d.html", OutputBase, Index++);
      fout = fopen (Filename, "w");
      if (fout == NULL)
        {
          printf ("Cannot create output file %03d.\n", Index - 1);
          goto Usage;
        }
      fprintf (fout, "%s\n", HeaderBuffer);
      fprintf (fout, "<h1 style=\"text-align: center;\">%s</h1>\n", Title);
      fprintf (fout, "<div style=\"text-align: center;\">");
      fprintf (fout, "<a href=\"%s%03d.html\">Previous</a> &nbsp;&nbsp;", OutputBase, Index - 2);
      fprintf (fout, "<a href=\"%s000.html\">Contents</a>", OutputBase);
      fprintf (fout, "<hr style=\"width: 100%%; height: 2px;\">\n");
      fprintf (fout, "<h1>The End</h1>\n");
      fprintf (fout, "\n</body>\n</html>\n");
      fclose (fout);
    }
  return (RetVal);
}
